package br.ufpb.di.ppgi.persistencia.query;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import br.com.caelum.vraptor.ioc.Component;
import br.ufpb.di.ppgi.negocio.modelo.convidado.Convidado;
import br.ufpb.di.ppgi.negocio.modelo.defesa.Defesa;
import br.ufpb.di.ppgi.negocio.modelo.defesa.DefesaStatus;
import br.ufpb.di.ppgi.negocio.modelo.homologacao.defesa.HomologacaoDefesa;
import br.ufpb.di.ppgi.negocio.modelo.participa.ParticipaDefesa;
import br.ufpb.di.ppgi.negocio.modelo.professorExterno.ProfessorExterno;
import br.ufpb.di.ppgi.negocio.modelo.usuario.Usuario;
import br.ufpb.di.ppgi.persistencia.domainstore.DomainStore;
import br.ufpb.di.ppgi.persistencia.iquery.IDefesaQuery;
import br.ufpb.di.ppgi.persistencia.pagination.HibernateQueryPagedList;

@Component
public class DefesaQuery extends AbstractJPAHibernateQuery implements IDefesaQuery {

	public DefesaQuery(DomainStore domainStore) {
		super(domainStore);
	}

	private Criteria blank() {
		return createCriteria(Defesa.class).addOrder(Order.desc("id"));
	}

	@Override
	public List<Defesa> listByOrientadorId(Long id) {
		return list(
				blank()
				.createAlias("orientador", "o")
				.add(Restrictions.eq("o.id", id))
		);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Defesa> listPendenciasByUsuario(Usuario usuario) {
		return (List<Defesa>) getSession()
			.createQuery("select pk.defesa from HomologacaoDefesa h where h.pk.colegiado = :colegiado and h.respondido = :respondido")
			.setParameter("colegiado", usuario)
			.setBoolean("respondido", false)
			.list();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<HomologacaoDefesa> listPendencias(Defesa defesa) {
		return (List<HomologacaoDefesa>) getSession()
			.createQuery("from HomologacaoDefesa h where h.pk.defesa.id = :defesaId and h.respondido = :respondido")
			.setLong("defesaId", defesa.getId())
			.setBoolean("respondido", false)
			.list();
	}

	@Override
	public Integer countVotosHomologacao(Defesa defesa, boolean homologado) {
		return count(createCriteria(HomologacaoDefesa.class)
				.add(Restrictions.eq("pk.defesa", defesa))
				.add(Restrictions.eq("respondido", true))
				.add(Restrictions.eq("homologado", homologado))
				);				
	}

	@Override
	public Integer countTotalVotos(Defesa defesa) {
		return count(createCriteria(HomologacaoDefesa.class)
				.add(Restrictions.eq("pk.defesa", defesa))
				);				
	}
	
	@Override
	public boolean isVotacaoInsuficiente(Defesa defesa) {
		return count(createCriteria(HomologacaoDefesa.class)
				.add(Restrictions.eq("pk.defesa", defesa))
				.add(Restrictions.eq("respondido", true))
				)  < 3;	
	}

	@Override
	public List<Defesa> listByStatus(DefesaStatus status) {
		return list(
				blank().add(Restrictions.eq("status", status))
			);
	}

	@Override
	public List<Usuario> listProfessores(Defesa defesa) {
		List<ParticipaDefesa> lista =  list(createCriteria(ParticipaDefesa.class)
				.add(Restrictions.eq("pk.defesa", defesa))
				);
		List<Usuario> professores = new ArrayList<Usuario>();
		for (ParticipaDefesa pd : lista) {
			professores.add(pd.getProfessor());
		}
		return professores;
	}
	
	@Override
	public List<ProfessorExterno> listProfExternos(Defesa defesa) {
		List<Convidado> lista =  list(createCriteria(Convidado.class)
				.add(Restrictions.eq("pk.defesa", defesa))
				);
		List<ProfessorExterno> professores = new ArrayList<ProfessorExterno>();
		for (Convidado pd : lista) {
			professores.add(pd.getProfExterno());
		}
		return professores;
	}

	@Override
	public HibernateQueryPagedList<Defesa> paginarByKeyAndStatusList(
			String key, List<DefesaStatus> statusAceitaveisDefesa) {
		
		DetachedCriteria dc = DetachedCriteria.forClass(Defesa.class)
				.add(Restrictions.in("status", statusAceitaveisDefesa));
		
		if (key != null && !key.trim().isEmpty())
			dc.add(Restrictions.ilike("titulo", key, MatchMode.ANYWHERE))
			  .add(Restrictions.ilike("resumo", key, MatchMode.ANYWHERE));
		
		return new HibernateQueryPagedList<Defesa>(dc,session);
	}
	
	
}
